home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 008 / src / hack.zap.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  10KB  |  469 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
  2.  
  3. #include "hack.h"
  4.  
  5. extern struct monst *makemon();
  6. struct monst *bhit();
  7. char *exclam();
  8.  
  9. char *fl[]= {
  10.     "magic missile",
  11.     "bolt of fire",
  12.     "sleep ray",
  13.     "bolt of cold",
  14.     "death ray"
  15. };
  16.  
  17. dozap()
  18. {
  19.     register struct obj *obj;
  20.     register struct monst *mtmp;
  21.     xchar zx,zy;
  22.     register int num;
  23.  
  24.     obj = getobj("/", "zap");
  25.     if(!obj) return(0);
  26.     if(obj->spe < 0 || (obj->spe == 0 && rn2(121))) {
  27.         pline("Nothing Happens");
  28.         return(1);
  29.     }
  30.     if(obj->spe == 0)
  31.         pline("You wrest one more spell from the worn-out wand.");
  32.     if(!(objects[obj->otyp].bits & NODIR) && !getdir())
  33.         return(1); /* make him pay for knowing !NODIR */
  34.     obj->spe--;
  35.     if(objects[obj->otyp].bits & IMMEDIATE) {
  36.         if((u.uswallow && (mtmp = u.ustuck)) ||
  37.            (mtmp = bhit(u.dx,u.dy,rn1(8,6),0))) {
  38.             wakeup(mtmp);
  39.             switch(obj->otyp) {
  40.             case WAN_STRIKING:
  41.                 if(rnd(20) < 10+mtmp->data->ac) {
  42.                     register int tmp = d(2,12);
  43.                     hit("wand", mtmp, exclam(tmp));
  44.                     mtmp->mhp -= tmp;
  45.                     if(mtmp->mhp < 1) killed(mtmp);
  46.                 } else miss("wand", mtmp);
  47.                 break;
  48.             case WAN_SLOW_MONSTER:
  49.                 mtmp->mspeed = MSLOW;
  50.                 break;
  51.             case WAN_SPEED_MONSTER:
  52.                 mtmp->mspeed = MFAST;
  53.                 break;
  54.             case WAN_UNDEAD_TURNING:
  55.                 if(index("WVZ&",mtmp->data->mlet)) {
  56.                     mtmp->mhp -= rnd(8);
  57.                     if(mtmp->mhp<1) killed(mtmp);
  58.                     else mtmp->mflee = 1;
  59.                 }
  60.                 break;
  61.             case WAN_POLYMORPH:
  62.                 if( newcham(mtmp,&mons[rn2(CMNUM)]) )
  63.                     objects[obj->otyp].oc_name_known = 1;
  64.                 break;
  65.             case WAN_CANCELLATION:
  66.                 mtmp->mcan = 1;
  67.                 break;
  68.             case WAN_TELEPORT_MONSTER:
  69.                 rloc(mtmp);
  70.                 break;
  71.             case WAN_MAKE_INVISIBLE:
  72.                 mtmp->minvis = 1;
  73.                 break;
  74. #ifdef WAN_PROBING
  75.             case WAN_PROBING:
  76.                 mstatusline(mtmp);
  77.                 break;
  78. #endif WAN_PROBING
  79.             default:
  80.                 pline("What an interesting wand (%d)",
  81.                     obj->otyp);
  82.                 impossible();
  83.             }
  84.         }
  85.     } else {
  86.     switch(obj->otyp){
  87.         case WAN_LIGHT:
  88.             litroom(TRUE);
  89.             break;
  90.         case WAN_SECRET_DOOR_DETECTION:
  91.             if(!findit()) return(1);
  92.             break;
  93.         case WAN_CREATE_MONSTER:
  94.             { register int cnt = 1;
  95.             if(!rn2(23)) cnt += rn2(7) + 1;
  96.             while(cnt--)
  97.                 (void) makemon((struct permonst *) 0, u.ux, u.uy);
  98.             }
  99.             break;
  100.         case WAN_WISHING:
  101.             { char buf[BUFSZ];
  102.               register struct obj *otmp;
  103.               extern struct obj *readobjnam(), *addinv();
  104.               if(u.uluck + rn2(5) < 0) {
  105.             pline("Unfortunately, nothing happens.");
  106.             break;
  107.               }
  108.               pline("You may wish for an object. What do you want? ");
  109.               getlin(buf);
  110.               otmp = readobjnam(buf);
  111.               otmp = addinv(otmp);
  112.               prinv(otmp);
  113.               break;
  114.             }
  115.         case WAN_DIGGING:
  116.             { register struct rm *room;
  117.               register int digdepth;
  118.             if(u.uswallow) {
  119.                 pline("You pierce %s's stomach wall!",
  120.                     monnam(u.ustuck));
  121.                 u.uswallow = 0;
  122.                 mnexto(u.ustuck);
  123.                 u.ustuck->mhp = 1;    /* almost dead */
  124.                 u.ustuck = 0;
  125.                 setsee();
  126.                 docrt();
  127.                 break;
  128.             }
  129.             zx = u.ux+u.dx;
  130.             zy = u.uy+u.dy;
  131.             if(!isok(zx,zy)) break;
  132.             digdepth = 4 + rn2(10);
  133.             if(levl[zx][zy].typ == CORR) num = CORR;
  134.             else num = ROOM;
  135.             Tmp_at(-1, '*');    /* open call */
  136.             while(digdepth--) {
  137.                 if(zx == 0 || zx == COLNO-1 ||
  138.                      zy == 0 || zy == ROWNO-1)
  139.                     break;
  140.                 room = &levl[zx][zy];
  141.                 Tmp_at(zx,zy);
  142.                 if(!xdnstair){
  143.                     if(zx < 3 || zx > COLNO-3 ||
  144.                         zy < 3 || zy > ROWNO-3)
  145.                         break;
  146.                     if(room->typ == HWALL ||
  147.                         room->typ == VWALL){
  148.                         room->typ = ROOM;
  149.                         break;
  150.                     }
  151.                 } else if(num == ROOM || num == 10){
  152.                     if(room->typ != ROOM && room->typ) {
  153.                         if(room->typ != CORR)
  154.                             room->typ = DOOR;
  155.                         if(num == 10) break;
  156.                         num = 10;
  157.                     } else if(!room->typ)
  158.                         room->typ = CORR;
  159.                 } else {
  160.                     if(room->typ != CORR && room->typ) {
  161.                         room->typ = DOOR;
  162.                         break;
  163.                     } else room->typ = CORR;
  164.                 }
  165.                 mnewsym(zx,zy);
  166.                 zx += u.dx;
  167.                 zy += u.dy;
  168.             }
  169.             mnewsym(zx,zy);    /* not always necessary */
  170.             Tmp_at(-1,-1);    /* closing call */
  171.             break;
  172.             }
  173.         default:
  174.             buzz((int) obj->otyp - WAN_MAGIC_MISSILE,
  175.                 u.ux, u.uy, u.dx, u.dy);
  176.             break;
  177.         }
  178.         if(!objects[obj->otyp].oc_name_known) {
  179.             u.urexp += 10;
  180.             objects[obj->otyp].oc_name_known = 1;
  181.         }
  182.     }
  183.     return(1);
  184. }
  185.  
  186. char *
  187. exclam(force)
  188. register int force;
  189. {
  190.     /* force == 0 occurs e.g. with sleep ray */
  191.     /* note that large force is usual with wands so that !! would
  192.         require information about hand/weapon/wand */
  193.     return( (force < 0) ? "?" : (force <= 4) ? "." : "!" );
  194. }
  195.  
  196. hit(str,mtmp,force)
  197. register char *str;
  198. register struct monst *mtmp;
  199. register char *force;        /* usually either "." or "!" */
  200. {
  201.     if(!cansee(mtmp->mx,mtmp->my)) pline("The %s hits it.", str);
  202.     else pline("The %s hits %s%s", str, monnam(mtmp), force);
  203. }
  204.  
  205. miss(str,mtmp)
  206. register char *str;
  207. register struct monst *mtmp;
  208. {
  209.     if(!cansee(mtmp->mx,mtmp->my)) pline("The %s misses it.",str);
  210.     else pline("The %s misses %s.",str,monnam(mtmp));
  211. }
  212.  
  213. /* sets bhitpos to the final position of the weapon thrown */
  214. /* coord bhitpos; */
  215.  
  216. /* check !u.uswallow before calling bhit() */
  217. struct monst *
  218. bhit(ddx,ddy,range,sym)
  219. register int ddx,ddy,range;
  220. char sym;
  221. {
  222.     register struct monst *mtmp;
  223.  
  224.     bhitpos.x = u.ux;
  225.     bhitpos.y = u.uy;
  226.  
  227.     if(sym) tmp_at(-1, sym);    /* open call */
  228.     while(range--) {
  229.         bhitpos.x += ddx;
  230.         bhitpos.y += ddy;
  231.         if(mtmp = m_at(bhitpos.x,bhitpos.y)){
  232.             if(sym) tmp_at(-1, -1);    /* close call */
  233.             return(mtmp);
  234.         }
  235.         if(levl[bhitpos.x][bhitpos.y].typ<CORR) {
  236.             bhitpos.x -= ddx;
  237.             bhitpos.y -= ddy;
  238.             break;
  239.         }
  240.         if(sym) tmp_at(bhitpos.x, bhitpos.y);
  241.     }
  242.     if(sym) tmp_at(-1, 0);    /* leave last symbol */
  243.     return(0);
  244. }
  245.  
  246. struct monst *
  247. boomhit(dx,dy) {
  248.     register int i, ct;
  249.     register struct monst *mtmp;
  250.     char sym = ')';
  251.     extern schar xdir[], ydir[];
  252.  
  253.     bhitpos.x = u.ux;
  254.     bhitpos.y = u.uy;
  255.  
  256.     for(i=0; i<8; i++) if(xdir[i] == dx && ydir[i] == dy) break;
  257.     tmp_at(-1, sym);    /* open call */
  258.     for(ct=0; ct<10; ct++) {
  259.         if(i == 8) i = 0;
  260.         sym = ')' + '(' - sym;
  261.         tmp_at(-2, sym);    /* change let call */
  262.         dx = xdir[i];
  263.         dy = ydir[i];
  264.         bhitpos.x += dx;
  265.         bhitpos.y += dy;
  266.         if(mtmp = m_at(bhitpos.x, bhitpos.y)){
  267.             tmp_at(-1,-1);
  268.             return(mtmp);
  269.         }
  270.         if(levl[bhitpos.x][bhitpos.y].typ<CORR) {
  271.             bhitpos.x -= dx;
  272.             bhitpos.y -= dy;
  273.             break;
  274.         }
  275.         if(bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */
  276.             if(rn2(20) >= 10+u.ulevel){    /* we hit ourselves */
  277.                 (void) thitu(10, rnd(10), "boomerang");
  278.                 break;
  279.             } else {    /* we catch it */
  280.                 tmp_at(-1,-1);
  281.                 pline("Skillfully, you catch the boomerang.");
  282.                 return((struct monst *) -1);
  283.             }
  284.         }
  285.         tmp_at(bhitpos.x, bhitpos.y);
  286.         if(ct % 5 != 0) i++;
  287.     }
  288.     tmp_at(-1, -1);    /* do not leave last symbol */
  289.     return(0);
  290. }
  291.  
  292. char
  293. dirlet(dx,dy) register int dx,dy; {
  294.     return
  295.         (dx == dy) ? '\\' : (dx && dy) ? '/' : dx ? '-' : '|';
  296. }
  297.  
  298. /* type < 0: monster spitting fire at you */
  299. buzz(type,sx,sy,dx,dy)
  300. register int type;
  301. register xchar sx,sy;
  302. register int dx,dy;
  303. {
  304.     register char *fltxt = (type < 0) ? "blaze of fire" : fl[type];
  305.     struct rm *lev;
  306.     xchar range;
  307.     struct monst *mon;
  308.  
  309.     if(u.uswallow) {
  310.         register int tmp;
  311.  
  312.         if(type < 0) return;
  313.         tmp = zhit(u.ustuck, type);
  314.         pline("The %s rips into %s%s",
  315.             fltxt, monnam(u.ustuck), exclam(tmp));
  316.         return;
  317.     }
  318.     if(type < 0) pru();
  319.     range = rn1(7,7);
  320.     Tmp_at(-1, dirlet(dx,dy));    /* open call */
  321.     while(range-- > 0) {
  322.         sx += dx;
  323.         sy += dy;
  324.         if((lev = &levl[sx][sy])->typ) Tmp_at(sx,sy);
  325.         else {
  326.             int bounce = 0;
  327.             if(cansee(sx-dx,sy-dy)) pline("The %s bounces!",fltxt);
  328.             if(levl[sx][sy-dy].typ > DOOR) bounce = 1;
  329.             if(levl[sx-dx][sy].typ > DOOR) {
  330.                 if(!bounce || rn2(2)) bounce = 2;
  331.             }
  332.             switch(bounce){
  333.             case 0:
  334.                 dx = -dx;
  335.                 dy = -dy;
  336.                 continue;
  337.             case 1:
  338.                 dy = -dy;
  339.                 sx -= dx;
  340.                 break;
  341.             case 2:
  342.                 dx = -dx;
  343.                 sy -= dy;
  344.                 break;
  345.             }
  346.             Tmp_at(-2,dirlet(dx,dy));
  347.             continue;
  348.         }
  349.         if((mon = m_at(sx,sy)) &&
  350.            (type >= 0 || mon->data->mlet != 'D')) {
  351.             wakeup(mon);
  352.             if(rnd(20) < 18 + mon->data->ac) {
  353.                 register int tmp = zhit(mon,type);
  354.                 if(mon->mhp < 1) {
  355.                     if(type < 0) {
  356.                         if(cansee(mon->mx,mon->my))
  357.                           pline("%s is killed by the %s!",
  358.                         Monnam(mon), fltxt);
  359.                         mondied(mon);
  360.                     } else
  361.                         killed(mon);
  362.                 } else
  363.                     hit(fltxt, mon, exclam(tmp));
  364.                 range -= 2;
  365.             } else
  366.                 miss(fltxt,mon);
  367.         } else if(sx == u.ux && sy == u.uy) {
  368.             if(rnd(20) < 18+u.uac) {
  369.                 register int dam = 0;
  370.                 range -= 2;
  371.                 pline("The %s hits you!",fltxt);
  372.                 switch(type) {
  373.                 case 0:
  374.                     dam = d(2,6);
  375.                     break;
  376.                 case -1:    /* dragon fire */
  377.                 case 1:
  378.                     if(Fire_resistance)
  379.                         pline("You don't feel hot!");
  380.                     else dam = d(6,6);
  381.                     break;
  382.                 case 2:
  383.                     nomul(-rnd(25)); /* sleep ray */
  384.                     break;
  385.                 case 3:
  386.                     if(Cold_resistance)
  387.                         pline("You don't feel cold!");
  388.                     else dam = d(6,6);
  389.                     break;
  390.                 case 4:
  391.                     u.uhp = -1;
  392.                 }
  393.                 losehp(dam,fltxt);
  394.             } else pline("The %s whizzes by you!",fltxt);
  395.         }
  396.         if(lev->typ <= DOOR) {
  397.             int bounce = 0, rmn;
  398.             if(cansee(sx,sy)) pline("The %s bounces!",fltxt);
  399.             range--;
  400.             if(!dx || !dy || !rn2(20)){
  401.                 dx = -dx;
  402.                 dy = -dy;
  403.             } else {
  404.               if((rmn = levl[sx][sy-dy].typ) > DOOR &&
  405.                 (
  406.                  rmn >= ROOM ||
  407.                 levl[sx+dx][sy-dy].typ > DOOR)){
  408.                 bounce = 1;
  409.               }
  410.               if((rmn = levl[sx-dx][sy].typ) > DOOR &&
  411.                 (
  412.                  rmn >= ROOM ||
  413.                 levl[sx-dx][sy+dy].typ > DOOR)){
  414.                 if(!bounce || rn2(2)){
  415.                     bounce = 2;
  416.                 }
  417.               }
  418.               switch(bounce){
  419.               case 0:
  420.                 dy = -dy;
  421.                 dx = -dx;
  422.                 break;
  423.               case 1:
  424.                 dy = -dy;
  425.                 break;
  426.               case 2:
  427.                 dx = -dx;
  428.                 break;
  429.               }
  430.               Tmp_at(-2, dirlet(dx,dy));
  431.             }
  432.         }
  433.     }
  434.     Tmp_at(-1,-1);
  435. }
  436.  
  437. zhit(mon,type)            /* returns damage to mon */
  438. register struct monst *mon;
  439. register int type;
  440. {
  441.     register int tmp = 0;
  442.  
  443.     switch(type) {
  444.     case 0:            /* magic missile */
  445.         tmp = d(2,6);
  446.         break;
  447.     case -1:        /* Dragon blazing fire */
  448.     case 1:            /* fire */
  449.         if(index("Dg", mon->data->mlet)) break;
  450.         tmp = d(6,6);
  451.         if(mon->data->mlet == 'Y') tmp += 7;
  452.         break;
  453.     case 2:            /* sleep*/
  454.         mon->mfroz = 1;
  455.         break;
  456.     case 3:            /* cold */
  457.         if(index("YFgf", mon->data->mlet)) break;
  458.         tmp = d(6,6);
  459.         if(mon->data->mlet == 'D') tmp += 7;
  460.         break;
  461.     case 4:            /* death*/
  462.         if(index("WVZ",mon->data->mlet)) break;
  463.         tmp = mon->mhp+1;
  464.         break;
  465.     }
  466.     mon->mhp -= tmp;
  467.     return(tmp);
  468. }
  469.